import ApiConstants from "../common/ApiConstants";
import JsonUtil from "./JsonUtil";
import Config from "../config";
import { isEmpty } from "./utils";
import { toastShort } from "./ToastUtils";
import StorageUtil from "./StorageUtil";
import NavigatorUtil from "./NavigatorUtil";

const NetWorkUtil = {
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  postWithoutLogin: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      const bodyStr = JsonUtil.jsonToStr(bodyObj);
      const option = {
        method: "POST",
        headers: {
          "Content-type": "application/json;charset=UTF-8",
        },
        body: bodyStr,
      };

      NetWorkUtil.doFetch(url, option)
        .then(response => {
          resolve(response);
        })
        .catch(err => {
          console.log(err);
          reject(err);
        });
    });
  },

  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  getWithoutLogin: (apiCode, queryObj) => {
    return new Promise((resolve, reject) => {
      let url = NetWorkUtil.getHostUrl(apiCode);
      if (queryObj) {
        const toQueryString = NetWorkUtil.toQueryString(queryObj);
        if (!isEmpty(toQueryString)) {
          if (url.indexOf("?") > -1) {
            url = `${url}&${toQueryString}`;
          } else {
            url = `${url}?${toQueryString}`;
          }
        }
      }
      const option = {
        method: "GET",
        query: queryObj,
      };

      NetWorkUtil.doFetch(url, option)
        .then(response => {
          resolve(response);
        })
        .catch(err => {
          reject(err);
        });
    });
  },

  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  post: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      bodyObj.token = global.token;
      const bodyStr = JsonUtil.jsonToStr(bodyObj);

      StorageUtil.loadToken()
        .then(token => {
          // console.log(signedParam)
          const option = {
            method: "POST",
            headers: {
              "Content-type": "application/json;charset=UTF-8",
              sign: global.sign,
            },
            body: bodyStr,
          };

          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
        });
    });
  },
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  postWithForm: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      const bodyStr = NetWorkUtil.getFormData(bodyObj);
      console.log(bodyStr);

      StorageUtil.loadToken()
        .then(token => {
          // console.log(signedParam)
          const option = {
            method: "POST",
            headers: {
              "Content-Type": "multipart/form-data",
              Authorization: token,
            },
            body: bodyStr,
          };

          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
        });
    });
  },
  getFormData: object => {
    const formData = new FormData();
    Object.keys(object).forEach(key => formData.append(key, object[key]));
    return formData;
  },
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  put: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      const bodyStr = JsonUtil.jsonToStr(bodyObj);

      StorageUtil.loadToken()
        .then(token => {
          // console.log(signedParam)
          const option = {
            method: "PUT",
            headers: {
              "Content-type": "application/json;charset=UTF-8",
              Authorization: token,
            },
            body: bodyStr,
          };

          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
          reject(err);
        });
    });
  },
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  patch: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      const bodyStr = JsonUtil.jsonToStr(bodyObj);

      StorageUtil.loadToken()
        .then(token => {
          // console.log(signedParam)
          const option = {
            method: "PATCH",
            headers: {
              "Content-type": "application/json;charset=UTF-8",
              Authorization: token,
            },
            body: bodyStr,
          };

          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
          reject(err);
        });
    });
  },
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param bodyObj 参数Json对象
   */
  delete: (apiCode, bodyObj) => {
    return new Promise((resolve, reject) => {
      const url = NetWorkUtil.getHostUrl(apiCode);
      const bodyStr = JsonUtil.jsonToStr(bodyObj);

      StorageUtil.loadToken()
        .then(token => {
          // console.log(signedParam)
          const option = {
            method: "DELETE",
            headers: {
              "Content-type": "application/json;charset=UTF-8",
              Authorization: token,
            },
            body: bodyStr,
          };

          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
          reject(err);
        });
    });
  },
  /**
   * 请求api，获取数据
   * @param apiCode
   * @param queryObj
   */
  get: (apiCode, queryObj) => {
    return new Promise((resolve, reject) => {
      let url = NetWorkUtil.getHostUrl(apiCode);

      if (queryObj) {
        const toQueryString = NetWorkUtil.toQueryString(queryObj);
        if (!isEmpty(toQueryString)) {
          if (url.indexOf("?") > -1) {
            url = `${url}&${toQueryString}`;
          } else {
            url = `${url}?${toQueryString}`;
          }
        }
      }
      StorageUtil.loadToken()
        .then(token => {
          const option = {
            method: "GET",
            headers: {
              sign: global.sign,
            },
            query: queryObj,
          };
          NetWorkUtil.doFetch(url, option)
            .then(response => {
              resolve(response);
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log("Loadtoken", err);
          reject(err);
          toastShort("需要登录");
          NavigatorUtil.goLogin();
        });
    });
  },

  /**
   * 打印request日志
   */
  logRequestInfo: (option, url, bodyStr) => {
    if (console.group) {
      if (option) {
        console.group(`Api Request ${option.method}`);
      } else {
        console.group("Api Request");
      }
      if (option && option.method === "GET") {
        const token = option.headers && option.headers.Authorization ? option.headers.Authorization : "";

        if (url.indexOf("?") > -1) {
          console.log("Api Url：", `${url}&access_token=${token}`);
        } else {
          console.log("Api Url：", `${url}?access_token=${token}`);
        }
      } else {
        console.log("Api Url：", url);
      }
      if (option && option.body && typeof option.body === "string") {
        console.log("Api Params: ", JsonUtil.strToJson(bodyStr));
      }
      if (option && option.query) {
        console.log("Api Query: ", option.query);
      }
      console.groupEnd();
    } else {
      console.log("Api Request", { url, bodyStr });
    }
  },

  /**
   * 请求网络数据
   * @param url
   * @param option
   * @private
   */
  doFetch: (url, option) => {
    NetWorkUtil.logRequestInfo(option, url, option.body);
    console.log(option);
    return new Promise((resolve, reject) => {
      fetch(url, option)
        .then(response => {
          console.log(`Response :`, response);
          console.log(`Api Url :${url}`);
          response
            .json()
            .then(res => {
              console.log("responseObjRes :", res);
              const { data, status } = res;
              console.log("responseObj :", data);
              if (status === "ok") {
                resolve(data);
              } else {
                reject(res);
              }
            })
            .catch(err => {
              reject(err);
            });
        })
        .catch(err => {
          console.log(err);
          if (
            err.message.indexOf("Unexpected token < in JSON at position 0") > -1
            || err.message.indexOf("token '<'") > -1
          ) {
            reject(new Error("数据解析错误，请稍后重试"));
          } else if (err.message === "Network request failed") {
            reject(new Error("网络请求失败，请检查网络后重试"));
          } else {
            reject(err);
          }
        });
    });
  },

  /**
   *
   * @param PicturePath
   * @param fileType
   */
  uploadPicture: PicturePath => {
    return new Promise((resolve, reject) => {
      if (PicturePath) {
        StorageUtil.loadToken()
          .then(token => {
            // Create the form data object
            const data = new FormData();
            data.append("file", { uri: PicturePath, name: "a.jpg", type: "image/jpg" });

            // Create the config object for the POST
            // You typically have an OAuth2 token that you use for authentication
            const option = {
              method: "POST",
              headers: {
                "Content-Type": "multipart/form-data",
              },
              body: data,
            };

            const uploadUrl = NetWorkUtil.getHostUrl(ApiConstants.UPLOAD_PICTURE);

            NetWorkUtil.doFetch(uploadUrl, option)
              .then(response => {
                resolve(response);
              })
              .catch(err => {
                reject(err);
              });
          })
          .catch(err => {
            reject(err);
          });
      }
    });
  },
  /**
   * 获取api url
   * @param apiCode
   * @param version
   * @returns {string}
   */
  getHostUrl: apiCode => {
    return `${Config.BASE_URL}/api/${apiCode}`;
  },

  getUploadHeaderUrl: fullUrl => {
    return fullUrl.split(`${Config.BASE_URL}/`)[1];
  },
  /**
   * 获取file url
   * @param apiCode
   * @param version
   * @returns {string}
   */
  getFileUrl: apiCode => {
    if (apiCode.indexOf("https://") > -1 || apiCode.indexOf("http://") > -1) {
      return apiCode;
    }
    return `${Config.BASE_URL}${apiCode}`;
  },

  /**
   *
   * @param obj
   * @returns {string}
   */
  toQueryString: obj => {
    // console.log(obj)

    return obj
      ? Object.keys(obj)
        .sort()
        .map(key => {
          const val = obj[key];
          if (Array.isArray(val)) {
            return val
              .sort()
              .map(val2 => {
                return `${encodeURIComponent(key)}=${encodeURIComponent(val2)}`;
              })
              .join("&");
          }
          return `${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
        })
        .join("&")
      : "";
  },
};

export default NetWorkUtil;
